import { Compiler, Injectable, Injector } from "@angular/core";
import { AppLocalizationService } from "@app/shared/common/localization/app-localization.service";
import { AppBsModalService } from "@shared/common/appBsModal/app-bs-modal.service";
import { FileUploadHelper } from "@shared/helpers/FileUploadHelper";
import { ContentListConfigItem, CreateOrUpdateImageTextInput, ExtendDataConfig, FormField, GetMotherSiteInput, ImageTextConfig, ManualSyncInput, MenuInfoConfig, MenuInfoDataType, MenuInfoServiceProxy, MenuInfoSyncServiceProxy, NameValueDto, TabFormConfig } from "@shared/service-proxies/service-proxies";
import { AppNotifyService } from "@shared/utils/service/app-notify.service";
import { DiyFormService } from "../diy-form-service";
import { ManualSyncModalComponent } from "../manual-sync/manual-sync-modal.component";
import { IImageTextComponent } from "./IImageText-component";

export interface IImageTextDataItemBase {
    dataType: MenuInfoDataType;
    key: string | undefined;
    formName: string | undefined;
    listName: string | undefined;
    name: string | undefined;
    tabNames: TabFormConfig[] | undefined;
}

@Injectable()
export class ImageTextService {

    static readonly extendKey = "extended";

    constructor(
        private _menuInfoServiceProxy: MenuInfoServiceProxy,
        private _diyFormService: DiyFormService,
        private _appLocalizationService: AppLocalizationService,
        private notify: AppNotifyService,
        private compiler: Compiler,
        private _modalService: AppBsModalService,
        private _menuInfoSyncService: MenuInfoSyncServiceProxy
    ) {

    }

    getDefaultConfig(): MenuInfoConfig{
        return new MenuInfoConfig({
            disableSeo: false,
            localNames: {},
            extended : new  ExtendDataConfig({enable :false,formName: null}),
            imageText : new ImageTextConfig({enable : false, groups:[]}),
            forms :{},
            lists:{}
        });
    }


    init(vm : IImageTextComponent, beforeInit:()=>void, afterInit:()=>void) {
        if (vm.cmpRef) {
            vm.cmpRef.destroy();
        }

        beforeInit && beforeInit();
        
        this._menuInfoServiceProxy.getConfigForMenuData(vm.kind).subscribe(result => {
            var data = KTUtil.jsonToCamelCase(result.config);
            vm.menuConfig =  new MenuInfoConfig(data);
            vm.permissionDic = result.permissions;
            vm.menuId = result.menuId;
            vm.menuName = result.displayName;

            afterInit && afterInit();
        });
    }

    initForms(vm : IImageTextComponent) {
		vm.data = {};
        this._menuInfoServiceProxy.getAllImageText(vm.kind, vm.menuId)
        .subscribe(result => {
            let html = '';
            let firstCollapse = true;
            vm.menuConfig.imageText.groups.forEach(t => {
                let formHtml = this.getHtmlForImageTextItem(t, vm, result, 'imageText.' + t.key, true, "");

                if(t.moreForms){
                    t.moreForms.forEach(moreForm =>{
                        formHtml += this.getHtmlForImageTextItem(moreForm, vm, result , 'imageText.' + t.key + '.' + moreForm.key, false, moreForm.showOrNot);
                    })
                }

                html += this.getCollapseContainerHtml(vm, formHtml, t.name, firstCollapse);
                firstCollapse = false;
            });

            let tempFunc = function () {
                this.data = vm.data;
                this.listData = vm.listData;
                this.Collapse = vm.Collapse;
                this.permissions = {};
                this.permissionDic = vm.permissionDic;
                this.permissions.create = vm.permissionDic['Pages.Tenant.MenuInfo.ImageText.Create'];
                this.permissions.edit = vm.permissionDic['Pages.Tenant.MenuInfo.ImageText.Edit'];
                this.permissions.delete = vm.permissionDic['Pages.Tenant.MenuInfo.ImageText.Delete'];
                this.kind = vm.kind;
                this.randomId = vm.randomId;
                this.isTemporary = vm.isTemporary;
                this.listConfig = vm.listConfig;

                this.createNews = (key: string) => { vm.createNews(key) };
                this.editModule = (event) => { vm.editModule(event.record, event.key) };
            };

            this._diyFormService.createFormComponentFactory(this.compiler, html, tempFunc).then(factory => {
                const injector = Injector.create({ providers: [], parent: vm.vc.injector });
                const cmpRef = vm.vc.createComponent(factory, 0, injector, []);

                cmpRef.instance.name = "dynamic-menuInfo-component";

                vm.cmpRef = cmpRef;
            });
        });
    }

    private getHtmlForImageTextItem(t: IImageTextDataItemBase, vm: IImageTextComponent, 
        result: { [key: string]: { [key: string]: any; }[]; }, key: string, isFirst: boolean, showOrNot) {
        let html: string = '';

        if (t.dataType === MenuInfoDataType.Single) {
            vm.data[key] = result[key][0];
            if (vm.data[key].id) {
                vm.randomId[key] = vm.data[key].id;
                vm.isTemporary[key] = false;
            } else {
                vm.randomId[key] = FileUploadHelper.newGuid();
                vm.isTemporary[key] = true;
            }
            let formName = KTUtil.toCamelCase(t.formName);
            let formConfig = vm.menuConfig.forms[formName];
            vm.formNameCache[key] = formName;
            this._diyFormService.afterLoadData(formConfig, vm.data[key]);

            html = this._diyFormService.getDetailPageTemplate(formConfig, key);
        } else if (t.dataType === MenuInfoDataType.List) {
            vm.listData[key] = result[key];

            let listName = t.listName;
            if (listName) {
                listName = KTUtil.toCamelCase(listName);
            }

            if(isFirst){
                html = this.getListContainerHtml(vm, key, listName,'', showOrNot);
            }else{
                //showOrNot 控制列表的显示隐藏
                html = this.getListContainerHtml(vm, key, listName, this._appLocalizationService.l(t.name), showOrNot);
            }
        } else if (t.dataType === MenuInfoDataType.Tabset) {

            let tabHtml = "<tabset class=\"tab-container tabbable-line\">";
            t.tabNames.forEach(tt => {
                key = 'imageText.' + t.key + '.' + tt.key;
                vm.data[key] = result[key][0];

                if (vm.data[key].id) {
                    vm.randomId[key] = vm.data[key].id;
                    vm.isTemporary[key] = false;
                } else {
                    vm.randomId[key] = FileUploadHelper.newGuid();
                    vm.isTemporary[key] = true;
                }

                let formName = KTUtil.toCamelCase(tt.formName);
                let formConfig = vm.menuConfig.forms[formName];
                vm.formNameCache[key] = formName;
                this._diyFormService.afterLoadData(formConfig, vm.data[key]);

                tabHtml += "<tab class=\"pt-3\" heading=\"" + this._appLocalizationService.l(tt.name) + "\">";
                tabHtml += this._diyFormService.getDetailPageTemplate(formConfig, key);
                tabHtml += "</tab>";
            });

            tabHtml += "</tabset>";
            html = tabHtml;
        }

        return html;
    }

    save(vm : IImageTextComponent){
        let i = 0;
        let j = 0;

        for (const key in vm.data) {
            if(!vm.saving){
                vm.saving = true;
            }

            if (Object.prototype.hasOwnProperty.call(vm.data, key)) {
                let data: { [key: string]: any } = {};
                for (let key2 in vm.data[key]) {
                    data[key2] = vm.data[key][key2];
                }
                let formConfig = vm.menuConfig.forms[vm.formNameCache[key]];
                this._diyFormService.beforeSubmit(formConfig, data);

                j++;

                let input = new CreateOrUpdateImageTextInput();
                if (data.id) {
                    input.id = data.id;
                }else{
                    input.randomId = vm.randomId[key];
                }
                input.values = data;
                input.menuId = vm.kind;
                input.dataKey = key;

                this._menuInfoServiceProxy.createOrUpdateImageText(input)
                    .subscribe(result => {
                        i++;
                        if (i === j) {
                            this.notify.success(this._appLocalizationService.l('SavedSuccessfully'));
                            vm.saving = false;
                            vm.callbackAfterSave();
                        }
                    }, error => {
                        console.log(error);
                        this.notify.warn(this._appLocalizationService.l('Error'));
                        i++;
                        if (i === j) {
                            vm.saving = false;
                        }
                    })
            }
        }
    }

    imageTextUpdate(vm : IImageTextComponent, key) {
        if(key !== ImageTextService.extendKey){
            this._menuInfoServiceProxy.getListData(vm.kind, vm.menuId, key)
            .subscribe(result=>{
                vm.listData[key] = result;
            });
        }
    }


    getDisplayName(vm:IImageTextComponent, name:string){
        if(vm.menuConfig.localNames){
            if(vm.menuConfig.localNames[name]){
                return vm.menuConfig.localNames[name];
            }
        }

        return this._appLocalizationService.l(name);
    }

    synchorization(vm:IImageTextComponent){
        const bsModalRef = this._modalService.show(ManualSyncModalComponent, {
            backdrop: 'static', class: 'modal-xl'
        });

        let params = new GetMotherSiteInput();
        params.menuId = vm.kind;

        let keyList : NameValueDto[] = [];
        if(vm.menuConfig.imageText.enable){
            vm.menuConfig.imageText.groups.forEach((val,index)=>{
                keyList.push(new NameValueDto({
                    name: val.name,
                    value: 'imageText.'+ val.key
                }));
            });
        }

        bsModalRef.content.configure({
            defaultParam: params,
            getDataFunc: (t)=> this._menuInfoSyncService.getImgTextFromMotherSite(t),
            getItems: (t)=> t,
            confirmFunc:(t)=> this._menuInfoSyncService.manualImgTextSynchorize(t),
            keyList: keyList,
            confirmDefaultParam : new ManualSyncInput()
        });
        bsModalRef.content.shown();
        bsModalRef.content.callback = () => {
            vm.reloadPage();
        };
    }

    getConfigByKey(vm:IImageTextComponent, dataKey:string):GetConfigByKeyResult{

        var config = vm.menuConfig;

        if (!dataKey)
        {
            return null;
        }

        var forms = config.forms;
        if (dataKey === ImageTextService.extendKey)
        {
            let formName = config.extended.formName;
            formName = KTUtil.toCamelCase(formName);
            let form = forms[formName];
            return {
                form : form,
                list: null,
                key : ImageTextService.extendKey,
                key2: null
            };
        }

        //图文
        var keyPath = dataKey.split(".");
        if (keyPath.length < 2)
        {
            return null;
        }

        var groupKey = keyPath[1];
        if (!config.imageText.groups)
        {
            return null;
        }
        var group = config.imageText.groups.find(t => t.key == groupKey);
        if (!group)
        {
            return null;
        }

        if (keyPath.length === 2)
        {
            return this.getFormConfigByKey(config, forms, group, "imageText." + groupKey);
        }

        //tab
        var result = this.tryGetTabFormConfig(forms, keyPath[2], "imageText." + groupKey, group);
        if (result !== null)
        {
            return result;
        }

        if (!group.moreForms)
        {
            return null;
        }

        var moreFormKey = keyPath[2];
        var moreForm = group.moreForms.find(t => t.key == moreFormKey);
        if (keyPath.length === 3)
        {
            return this.getFormConfigByKey(config, forms, moreForm, "imageText." + groupKey + "." + moreFormKey);
        }

        return this.tryGetTabFormConfig(forms, keyPath[3], "imageText." + groupKey + "." + moreFormKey, moreForm);
    }

    private tryGetTabFormConfig(forms: { [key: string]: FormField[]; }, tabKey: string ,
        key: string , group: IImageTextDataItemBase):GetConfigByKeyResult
    {
        if(!group.tabNames)
        {
            return null;
        }
        let tab = group.tabNames.find(t => t.key == tabKey);
        if (tab)
        {
            let formName = tab.formName;
            formName = KTUtil.toCamelCase(formName);
            let form = forms[formName];
            return {
                form : form,
                list: null,
                key : key,
                key2: tabKey
            };
        }
        return null;
    }

    private getFormConfigByKey(config:MenuInfoConfig, 
        forms: { [key: string]: FormField[]; }, group: IImageTextDataItemBase , key:string ):GetConfigByKeyResult
    {
        let listName = group.listName;
        let listConfig:ContentListConfigItem[] = null;
        if (listName && config.lists)
        {
            listName = KTUtil.toCamelCase(listName);
            listConfig = config.lists[listName];
        }
        let formName = group.formName;
        formName = KTUtil.toCamelCase(formName);
        let form = forms[formName];

        return {
            form : form,
            list: listConfig,
            key : key,
            key2: null
        };
    }


    private getCollapseContainerHtml(vm : IImageTextComponent, formHtml: string, groupName: string, firstCollapse: boolean) {
        vm.Collapse[groupName] = !firstCollapse;
        let id = "c" + FileUploadHelper.randomId();
        let html = '';
        html += "<div class=\"card card-default gutter-b  card-outline mb-4\">";
        html += "	<div class=\"card-header align-items-center border-0\">";
        html += "		<h3 class=\"card-title align-items-start flex-column marginHalf\">";
        html += "			<a class=\"font-weight-bolder text-dark\" href=\"javascript:;\" (click)=\"Collapse['" + groupName + "']=!Collapse['" + groupName + "']\"  [attr.aria-expanded]=\"!Collapse['" + groupName + "']\" aria-controls=\"" + id + "\">";
        html += "<i *ngIf=\"!Collapse['" + groupName + "']\" class=\"bi bi-chevron-compact-down\"></i><i *ngIf=\"Collapse['" + groupName + "']\" class=\"bi bi-chevron-right\"></i>&nbsp;" + this._appLocalizationService.l(groupName);
        html += "			</a>";
        html += "		</h3>";
        html += "	</div>";
        html += "	<div id=\"" + id + "\" class=\"collapse\" [collapse]=\"Collapse['" + groupName + "']\" [isAnimated]=\"true\">";
        html += "		<div class=\"card-body\">";
        html += formHtml;
        html += "		</div>";
        html += "	</div>";
        html += "</div>";
        return html;
    }

    private getListContainerHtml(vm : IImageTextComponent, key: string, listName: string, name:string, showOrNot: string) {
        // 'p-table' is not a known element
        if(!listName){
            listName = "defaultList";
        }

        let listConfig = null;
        if(vm.menuConfig.lists){
            listConfig = vm.menuConfig.lists[listName];
        }
        if(!listConfig){
            listConfig = [];
        }

        vm.listConfig[listName] = listConfig;

        let html = '<div>';
        if(showOrNot){
            html = '<div *ngIf="'+showOrNot+'">';
        }
        html += '<div class="row mb-1"><div class="col-sm-6">'+ name +'</div><div class="col-sm-6 text-right">';
        html += "    <button class=\"btn blue btn-circle btn-outline\" *ngIf=\"permissions.create\" ";
        html += "        (click)=\"createNews('" + key + "')\"><i class=\"fa fa-plus\"></i>{{\"CreateNew\" | localize}}</button>";
        html +='</div></div>';

        html += "<image-text-list [listConfig]=\"listConfig['" + listName + "']\" dataKey=\""+key+"\" [kind]=\"kind\" [records]=\"listData['" + key + "']\" [permissions]=\"permissions\" (editModule)=\"editModule($event)\"></image-text-list>";
        html +='</div>';
        return html;
    }
}

export interface GetConfigByKeyResult{
   form: FormField[];
   list:ContentListConfigItem[];
   key: string;
   key2: string;
}
